<?php
function encrypt_file($input_path, $output_path, $key)
{
	$result = false;
	if (empty($input_path) || empty($output_path) || strlen($key) != 16)
	{
		return $result;
	}
	$fp = fopen($input_path, "r");
	$fpw = fopen($output_path, "w");
	if ($fp && $fpw) {
		$content = "";
		while (!feof($fp)) {
			$content = fread($fp, 8);
			if (strlen($content) == 8)
			{
				$v = byte_to_uint32($content);
				list($a, $b) = encrypt($v, $key);
				fwrite($fpw, implode("", uint32_to_byte($a, $b)));
			}
			else
			{
				fwrite($fpw, $content);
			}
		}
		fclose($fp);
		fclose($fpw);
		$result = true;
	}
	return $result;
}

function decrypt_file($input_path, $output_path, $key)
{
	$result = false;
	if (empty($input_path) || empty($output_path) || strlen($key) != 16)
	{
		return $result;
	}
	$fp = fopen($input_path, "r");
	$fpw = fopen($output_path, "w");
	if ($fp && $fpw) {
		$content = "";
		while (!feof($fp)) {
			$content = fread($fp, 8);
			if (strlen($content) == 8)
			{
				$v = byte_to_uint32($content);
				list($a, $b) = decrypt($v, $key);
				fwrite($fpw, implode("", uint32_to_byte($a, $b)));
			}
			else
			{
				fwrite($fpw, $content);
			}
		}
		fclose($fp);
		fclose($fpw);
		$result = true;
	}
	return $result;
}

function uint32_to_byte($a, $b)
{
	$j = 0xFF;
	$r[0] = chr(to_uint32(to_uint32($a>>24)&$j));
	$r[1] = chr(to_uint32(to_uint32($a>>16)&$j));
	$r[2] = chr(to_uint32(to_uint32($a>>8)&$j));
	$r[3] = chr(to_uint32($a&$j));
	$r[4] = chr(to_uint32(to_uint32($b>>24)&$j));
	$r[5] = chr(to_uint32(to_uint32($b>>16)&$j));
	$r[6] = chr(to_uint32(to_uint32($b>>8)&$j));
	$r[7] = chr(to_uint32($b&$j));
	return $r;
}

function byte_to_uint32($c)
{
	$bt[0] = 0xFF000000;
	$bt[1] = 0x00FF0000;
	$bt[2] = 0x0000FF00;
	$bt[3] = 0x000000FF;
	
	$b = str_split($c, 1);
	for ($i=0; $i<count($b); $i++)
	{
		$b[$i] = ord($b[$i]);
	}
	if (count($b)<8)
	{
		for( $i=count($b); $i<8; $i++ )
		{
			$b[$i] = -1;
		}
	}
	$r[0] = to_uint32(to_uint32($b[0]<<24)&$bt[0])|to_uint32(to_uint32($b[1]<<16)&$bt[1])|to_uint32(to_uint32($b[2]<<8)&$bt[2])|to_uint32($b[3]&$bt[3]);
	$r[1] = to_uint32(to_uint32($b[4]<<24)&$bt[0])|to_uint32(to_uint32($b[5]<<16)&$bt[1])|to_uint32(to_uint32($b[6]<<8)&$bt[2])|to_uint32($b[7]&$bt[3]);
	return $r;
}

function encrypt($v, $k)
{
	$v0 = $v[0];
	$v1 = $v[1];
	$sum = 0;
    $delta=0x9e3779b9;
    $key = [];
    for ($i=0; $i<16; $i=$i+4)
	{
		$key[$i/4] = bin2hex(substr($k, $i, 1)).bin2hex(substr($k, $i+1, 1)).bin2hex(substr($k, $i+2, 1)).bin2hex(substr($k, $i+3, 1));
		$key[$i/4] = to_uint32(hexdec($key[$i/4]));
    }
    for ($i=0; $i<32; $i++)
	{
		$sum = to_uint32($sum+$delta);
        $v0 = to_uint32($v0+to_uint32(to_uint32(to_uint32($v1<<4)+$key[0]) ^ to_uint32($v1 + $sum) ^ to_uint32(to_uint32($v1>>5&0x07FFFFFF) + $key[1])));
        $v1 = to_uint32($v1+to_uint32(to_uint32(to_uint32($v0<<4)+$key[2]) ^ to_uint32($v0 + $sum) ^ to_uint32(to_uint32($v0>>5&0x07FFFFFF) + $key[3])));
	}

	return [$v0, $v1];
}

function decrypt($v, $k)
{
	$v0 = to_uint32($v[0]);
	$v1 = to_uint32($v[1]);
	$delta=0x9e3779b9;
	$sum = to_uint32($delta<<5);
    $key = [];
    for ($i=0; $i<16; $i=$i+4)
	{
		$key[$i/4] = bin2hex(substr($k, $i, 1)).bin2hex(substr($k, $i+1, 1)).bin2hex(substr($k, $i+2, 1)).bin2hex(substr($k, $i+3, 1));
		$key[$i/4] = to_uint32(hexdec($key[$i/4]));
    }
    for ($i=0; $i<32; $i++)
	{
        $v1 = to_uint32($v1-to_uint32(to_uint32(to_uint32($v0<<4)+$key[2]) ^ to_uint32($v0 + $sum) ^ to_uint32(to_uint32($v0>>5&0x07FFFFFF) + $key[3])));
		$v0 = to_uint32($v0-to_uint32(to_uint32(to_uint32($v1<<4)+$key[0]) ^ to_uint32($v1 + $sum) ^ to_uint32(to_uint32($v1>>5&0x07FFFFFF) + $key[1])));
		$sum = to_uint32($sum-$delta);
	}

	return [$v0, $v1];
}

function to_uint32($n)
{
	return $n & 0xFFFFFFFF;
}
set_time_limit(0);
encrypt_file("test.jpg", "teste.jpg", "abcdefghijklmnop");